
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>最大子数组和 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>最大子数组和 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是Java虚拟线程？它与传统的平台线程（Platform Threads）最核心的区别是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Java虚拟线程是由JVM而非操作系统管理的轻量级线程。其核心区别在于，虚拟线程与操作系统线程（OS线程）不是一对一的映射关系，许多虚拟线程可以共享同一个OS线程（即载体线程）；而平台线程则直接与一个OS线程一一对应，其数量受限于OS。</div>
          </div>
          <div class="card-source">来源: 1. 什么是虚拟线程（Virtual Threads）？</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">优势</div>
          <div class="card-question">虚拟线程主要解决了传统Java并发模型中的什么关键问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">优势</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">虚拟线程主要解决了平台线程的稀缺性和高成本问题。由于平台线程直接映射到昂贵的操作系统线程，其数量有限，这严重限制了服务器处理高并发I/O密集型任务的能力。虚拟线程通过解耦Java线程和OS线程，使得创建数百万个线程成为可能，从而极大地提高了应用程序的吞吐量和可伸缩性。</div>
          </div>
          <div class="card-source">来源: 1. 什么是虚拟线程（Virtual Threads）？</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">请描述虚拟线程的“挂载（Mounting）”和“卸载（Unmounting）”机制是如何工作的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">当虚拟线程需要执行计算时，JVM会将其“挂载”到一个平台线程（称为载体线程）上运行。当虚拟线程遇到阻塞I/O操作时，JVM会将其“卸载”，释放载体线程去执行其他虚拟线程的任务。当I/O操作完成后，虚拟线程会再次进入调度队列，等待被挂载到某个可用的载体线程上继续执行。</div>
          </div>
          <div class="card-source">来源: 2. 虚拟线程的工作原理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">什么情况下虚拟线程会被“钉住”（Pinning）？这会对系统性能产生什么负面影响？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">当虚拟线程在执行`synchronized`代码块或本地方法（JNI）时发生阻塞，它就会被“钉住”。钉住意味着虚拟线程无法从其载体线程上卸载，导致作为平台线程的载体线程也被阻塞。这会降低系统的可伸缩性，如果发生频繁，甚至可能导致承载虚拟线程的线程池被耗尽。</div>
          </div>
          <div class="card-source">来源: 2. 虚拟线程的工作原理 -> 线程钉住（Pinning）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">在使用虚拟线程时，为什么推荐使用 `java.util.concurrent.ReentrantLock` 来替代 `synchronized` 关键字？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为`synchronized`关键字在阻塞时会导致虚拟线程被“钉住”，使其无法从载体线程卸载，从而阻塞了宝贵的平台线程资源。相比之下，`ReentrantLock` 是“虚拟线程友好”的，它不会导致钉住，允许虚拟线程在等待锁时被安全地卸载，从而保持了虚拟线程并发模型的高可伸缩性优势。</div>
          </div>
          <div class="card-source">来源: 2. 虚拟线程的工作原理 -> 线程钉住（Pinning）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">对比</div>
          <div class="card-question">与传统的 `CompletableFuture` 相比，结构化并发（Structured Concurrency）在错误处理和任务管理方面提供了哪些优势？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">对比</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">结构化并发通过将一组并发任务视为一个单一的工作单元，极大地简化了错误处理和任务取消。它的核心优势在于：1. 可靠的错误处理：任何子任务失败都会导致整个作用域失败，并能可靠地捕获和传播异常。2. 清晰的任务生命周期：所有子任务都在一个明确的词法作用域（`try-with-resources`块）内完成。3. 简化的取消：当作用域结束或失败时，所有子任务会被自动取消。4. 增强的可观测性：线程转储（Thread Dumps）能清晰地展示任务的层级关系。</div>
          </div>
          <div class="card-source">来源: 4. 结构化并发（Structured Concurrency）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">如何使用 `StructuredTaskScope` 来实现“任意一个子任务成功，则整个任务成功”的并发模式？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">可以通过自定义 `StructuredTaskScope` 的子类来实现。在子类中，可以定义一个共享的成功结果变量。当任何一个子任务通过 `fork()` 成功完成时，就更新这个结果并调用 `shutdown()` 来取消所有其他正在运行的子任务。最后通过 `join()` 等待所有任务终止，并返回成功的结果。</div>
          </div>
          <div class="card-source">来源: 4. 结构化并发（Structured Concurrency）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">应用</div>
          <div class="card-question">虚拟线程最理想的应用场景是什么？请举例说明。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">应用</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">虚拟线程最适合用于处理大量并发、I/O密集型任务的场景，即“每个请求一个线程（thread-per-request）”风格的应用。典型例子包括：Web服务器、微服务网关、数据库连接代理等。在这些场景中，线程大部分时间都在等待网络或文件I/O，虚拟线程的轻量级特性使其能以极低成本支持海量并发连接，大幅提升系统吞吐量。</div>
          </div>
          <div class="card-source">来源: 5. 最佳实践和适用场景</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">为什么不应该使用虚拟线程来执行CPU密集型任务？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为虚拟线程的设计目标是提高I/O密集型任务的并发处理能力，而不是增加CPU的并行计算能力。虚拟线程并不会增加CPU核心的数量。将需要持续占用CPU的计算任务放在虚拟线程上运行，不仅无法获得性能提升，反而可能因为额外的调度开销而降低效率。这类任务仍然应该使用固定大小的平台线程池来执行。</div>
          </div>
          <div class="card-source">来源: 5. 最佳实践和适用场景</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
